<template>
    <div ref="theSentenceDiv">
        <span langsection="eng"><el-text><b>·</b></el-text><wordsSpanned/></span>
        <br/>
        <span langsection="chi">{{ thePhraseOWordUsage.chi }}</span>
    </div>
  <!--    <button @click="showTheProps">showProps</button>-->
  <!--    <br>-->
  <!--  some test:-->
  <!--  &lt;!&ndash;  {{ showInputChanged }}&ndash;&gt;-->
  <!--    <br>-->
    <div style="margin-top: 10px">
        <PhraseOWordPickInput ref="thePhraseOWordPickInput"
                              @showMarkCurrPicking="showMarkCurrPicking"
                              @pickKeyingSettled="showMarkCurrPickIndex"
                              @inputValueChange="inputValueChange"
                              @boldCurrTempPhraseOWord="boldCurrTempPhraseOWord"
                              @clearBoldsOfCurrTempPhraseOWord="clearBoldsOfCurrTempPhraseOWord"
                              @clearAllCurrTempMarkingInfo="clearAllCurrTempMarkingInfo"
                              @boldAllPickedPhrasesOWords="boldAllPickedPhrasesOWords"
                              @endPickingTheSentence="endPickingTheSentence"
                              :pickMode="pickMode"
                              :nodeWordsMapping="nodeWordsMapping"
                              :isCurrPickingMarkShowing="isCurrPickingMarkShowing"
                              :thePhraseOWordUsage="thePhraseOWordUsage"></PhraseOWordPickInput>
    </div>
  <!--    <br>-->
  <!--  the phrasesOWords:-->
</template>

<script setup>
import {computed, defineProps, ref, h, reactive, onMounted} from "vue";
// import PhraseOWordPickInput from "@/components/PhraseOWordPickInput.vue";
import PhraseOWordPickInput from "@/components/PhraseItComp/PhraseOWordPickInput.vue";
import PhraseOWordUsage from "@/models/PhraseOWordUsage";
import {useInputingStore} from "@/stores/inputingStore.js";
import {isValidObj} from "@/utils/ObjectUtils";
import {isInIOS} from "@/utils/EnvInfUtils.js";
import {clearAndPushAll} from "@/utils/ArrayUtil";


let inputingStore = useInputingStore();


let thePhraseOWordPickInput = ref();
let showInputChanged = ref("")

function inputValueChange(par) {
    showInputChanged.value = par;
}

// 手动移除订阅
// unsubscribe()

// console.log(inputingStore)
// const theInputingStore = useInputingStore();

let theProps = defineProps(["thePhraseOWordUsage", "pickMode"]);
//
// console.log("initiating PhraseOWordPickMarkingSingleEntryView.vue with ",theProps.pickMode);
// if(theProps.pickMode==='word'){
//     clearAndPushAll(theProps.thePhraseOWordUsage.pickedPhrasesOWords,[...theProps.thePhraseOWordUsage.pickedWordsTopMost]);
//     console.log("initiating PhraseOWordPickMarkingSingleEntryView.vue end change pickedPhrasesOWords");
// }
let theSentenceDiv = ref();
let computedAllWordSpanNodes = reactive([])


let theInputingStartWithNodeSpans = computed(() => {

    let result = [];
    computedAllWordSpanNodes.forEach((theSpanNode) => {
        let theWordIdx = parseInt(theSpanNode.getAttribute(PhraseOWordUsage.WORDIDX_ATTR));
        // console.log("computing theInputingStartWithNodeSpans");
        if (theSpanNode.textContent.trim().toLowerCase().startsWith(inputingStore.pickInputingValue.trim().toLowerCase()) && !theProps.thePhraseOWordUsage.anyInPickedPhase(theWordIdx)) {
            result.push(theSpanNode);
        }
    });
    return result;
});


function refreshWordsSpanNodesReactive() {
    computedAllWordSpanNodes.splice(0, computedAllWordSpanNodes.length);
    for (const node of theSentenceDiv.value.querySelectorAll("[" + PhraseOWordUsage.WORDIDX_ATTR + "]")) {
        // nodeWordsMapping.wordSpanNodes.push(new PhraseOWordUsage.WordSpanNode(null, matched.value[0], matched.value.index));
        // nodeWordsMapping["word" + matched.value.index] = wordSpanCnt;

        let wordIdx = node.getAttribute(PhraseOWordUsage.WORDIDX_ATTR);
        nodeWordsMapping.wordSpanNodes[nodeWordsMapping["word" + wordIdx]].node = node;
        computedAllWordSpanNodes.push(node);
    }
}

let isCurrPickingMarkShowing = ref(false);

const HILITER_ATTR = "hilighted";
const IDEX_MARKS = ["①", "②", "③", "④", "⑤", "⑥", "⑦", "⑧", "⑨"];


let theChooseOptionWordsFunc;

function showMarkCurrPickIndex() {

    if (theInputingStartWithNodeSpans.value.length > 1 && theInputingStartWithNodeSpans.value.length !== computedAllWordSpanNodes.length && isCurrPickingMarkShowing.value) {
        removeMarkCurrPickIndex();
        for (let aIdx = 0; aIdx < theInputingStartWithNodeSpans.value.length; aIdx++) {
            //下标mark
            let indexMarkSub = document.createElement("sub")
            // indexMarkSub.style.fontSize = "20px"
            indexMarkSub.innerHTML = IDEX_MARKS[aIdx];
            indexMarkSub.setAttribute(HILITER_ATTR, "1");
            theInputingStartWithNodeSpans.value[aIdx].appendChild(indexMarkSub);
        }

        //todo mark //not here,输入框能继续输入的问题??
        //todo 还是只在空格的时候才显示，选择
        //todo 下标只显示不选择? 直到按空格才可以选择?
        theChooseOptionWordsFunc = chooseOptionWords.bind(this);
        document.addEventListener('keydown', theChooseOptionWordsFunc);
        // thePhraseOWordPickInput.value.disableTheInput();
    }
}

function removeMarkCurrPickIndex() {
    let allIndexMarks = theSentenceDiv.value.querySelectorAll("sub[" + HILITER_ATTR + "]");
    for (const indexMark of allIndexMarks) {
        indexMark.removeAttribute(HILITER_ATTR);
        indexMark.parentNode.removeChild(indexMark);
    }
}

function showMarkCurrPicking() {
    refreshWordsSpanNodesReactive();

    removeCurrPickMark();
    if (theInputingStartWithNodeSpans.value.length > 0) {
        for (const thNode of theInputingStartWithNodeSpans.value) {
            let subMarkSpan = document.createElement("span");
            subMarkSpan.setAttribute("currPicking", "1");
            // thNode.classList = ["currPicking"];
            let theBoldNode = document.createElement("span");
            theBoldNode.innerHTML = thNode.textContent.substring(0, inputingStore.pickInputingValue.trim().length);
            theBoldNode.classList = ["currPicking"];
            let theRestText = document.createTextNode(thNode.textContent.substring(inputingStore.pickInputingValue.trim().length, thNode.textContent.length));
            thNode.removeChild(thNode.childNodes[0]);
            subMarkSpan.appendChild(theBoldNode);
            subMarkSpan.appendChild(theRestText);
            thNode.appendChild(subMarkSpan);
        }
        isCurrPickingMarkShowing.value = true;
    }
}

function removeCurrPickMark() {
    let currPickingNodes = theSentenceDiv.value.querySelectorAll("[currPicking]")
    for (const thNode of currPickingNodes) {
        // thNode.classList.remove("currPicking");
        let theTextNode = document.createTextNode(thNode.textContent);
        let thParentNode = thNode.parentNode;
        thParentNode.removeChild(thNode);
        thParentNode.appendChild(theTextNode);
    }
    removeMarkCurrPickIndex();
    isCurrPickingMarkShowing.value = false;
}

let nodeWordsMapping = {};

const wordsSpanned = () => {
    return (() => {
        // console.log("test vnode create");
        // return h("div",{innerHTML: 'hello'});
        let resultVnodes = [];
        nodeWordsMapping.wordSpanNodes = [];
        let matches = theProps.thePhraseOWordUsage.eng.matchAll(/[a-zA-Z]+/ig);
        let matched = matches.next();
        let preMatched;

        let wordSpanCnt = 0;

        function createWordSpanNode() {
            let theWordSpan = h("span", {
                [PhraseOWordUsage.WORDIDX_ATTR]: matched.value.index,
                innerHTML: matched.value[0]
            });
            nodeWordsMapping.wordSpanNodes.push(new PhraseOWordUsage.WordSpanNode(null, matched.value[0], matched.value.index));
            nodeWordsMapping["word" + matched.value.index] = wordSpanCnt;
            resultVnodes.push(theWordSpan);
            wordSpanCnt++;
        }

        if (matched.value) {
            if (matched.value.index !== 0) {
                resultVnodes.push(theProps.thePhraseOWordUsage.eng.substring(0, matched.value.index));
            } else {
                createWordSpanNode();
            }

            /* eslint-disable-next-line */
            while (true) {
                preMatched = matched;
                matched = matches.next();

                if (!matched.done && matched.value) {
                    resultVnodes.push(theProps.thePhraseOWordUsage.eng.substring(preMatched.value.index + preMatched.value[0].length, matched.value.index));
                    createWordSpanNode();
                } else {
                    break;
                }
            }

            let lastMatchedEnd = preMatched.value.index + preMatched.value[0].length;
            if (lastMatchedEnd !== theProps.thePhraseOWordUsage.eng.length) {
                resultVnodes.push(theProps.thePhraseOWordUsage.eng.substring(lastMatchedEnd, theProps.thePhraseOWordUsage.eng.length));
            }
        }
        return resultVnodes;
    })();
};

function boldCurrTempPhraseOWord() {
    if (inputingStore.currTempPhraseOWord.isValidPhraseOWord && isValidObj(inputingStore.currTempPhraseOWord)) {
        boldThePhraseOWord(inputingStore.currTempPhraseOWord, PhraseOWordUsage.TEMPCURRPHRASEOWORD_ATTR)
    }
}


function clearBoldsOfCurrTempPhraseOWord() {
    // console.log("clearBoldsOfCurrTempPhraseOWord");
    if (inputingStore.currTempPhraseOWord.isValidPhraseOWord && isValidObj(inputingStore.currTempPhraseOWord)) {
        // this.clearBoldsOfPhraseOWord(PhraseOWordUsage.TEMPCURRPHRASEOWORD_ATTR);
        clearBoldsOfPhraseOWord(PhraseOWordUsage.TEMPCURRPHRASEOWORD_ATTR, inputingStore.currTempPhraseOWord)
    }
}

function plainThePhraseOWord(phraseOWord, thePhraseOWordIdx) {

    let allNodesBetween;
    let allBolds = theSentenceDiv.value.querySelectorAll("b[" + PhraseOWordUsage.WORDBOLD_ATTR + "=\"" + thePhraseOWordIdx + "\"]");
    if (allBolds.length > 1) {
        let lastNodeOfbolds = allBolds[allBolds.length - 1].parentNode;
        allNodesBetween = getAllNodesBetween(phraseOWord, lastNodeOfbolds.getAttribute(PhraseOWordUsage.WORDIDX_ATTR));
    } else {
        allNodesBetween = getAllNodesBetween(phraseOWord);
    }

    for (const node of allNodesBetween) {
        let textNode = document.createTextNode(node.textContent);
        if (node.nodeName === "SPAN") {
            for (const childNode of node.childNodes) {
                node.removeChild(childNode);
            }
            node.appendChild(textNode);
        } else {
            let parentNode = node.parentNode;
            // parentNode.removeChild(node);
            parentNode.replaceChild(textNode, node)
            // parentNode.appendChild(textNode);
        }
    }
}

function boldThePhraseOWord(phraseOWord, thePhraseOWordIdx) {

    // plainThePhraseOWord(phraseOWord);
    // console.log("boldThePhraseOWord start with phraseOWord:",JSON.stringify(phraseOWord));
    clearBoldsOfPhraseOWord(thePhraseOWordIdx, phraseOWord);

    let allNodesBetween = getAllNodesBetween(phraseOWord);
    if (!allNodesBetween[0]) {
        return;
    }
    addSplitter(allNodesBetween);

    // console.log("boldThePhraseOWord start with phraseOWord m1:",JSON.stringify(phraseOWord));

    for (const theBetweenNode of allNodesBetween) {
        let boldIt = document.createElement("b");
        boldIt.setAttribute(PhraseOWordUsage.WORDBOLD_ATTR, thePhraseOWordIdx);

        if (theBetweenNode.nodeType === 3 || theBetweenNode.nodeName === "#text") {
            if (theBetweenNode.textContent && theBetweenNode.textContent.trim() !== "") {
                boldIt.appendChild(theBetweenNode.cloneNode(true));
                let theParentNode = theBetweenNode.parentNode;
                // theParentNode.removeChild(theBetweenNode);
                theParentNode.replaceChild(boldIt, theBetweenNode);
            }
        } else {
            for (const childNode of theBetweenNode.childNodes) {
                boldIt.appendChild(childNode.cloneNode(true));
                theBetweenNode.removeChild(childNode);
            }
            theBetweenNode.appendChild(boldIt);
        }
    }
}

function clearAllBoldsOfAllPickedPhrasesOWords() {
    for (const thePhraseOWordIdx in theProps.thePhraseOWordUsage.pickedPhrasesOWords) {
        clearBoldsOfPhraseOWord(thePhraseOWordIdx, theProps.thePhraseOWordUsage.pickedPhrasesOWords[thePhraseOWordIdx]);
        // this.clearBoldsOfPhraseOWord(thePhraseOWordIdx);
    }
}

/**
 * pickedPhrasesOWords and currTempPhraseOWord
 */
function boldAllPhrasesOWords() {
    boldAllPickedPhrasesOWords();
    boldCurrTempPhraseOWord();
}

function boldAllPickedPhrasesOWords() {
    clearAllBoldsOfAllPickedPhrasesOWords();
    for (const thePhraseOWord of theProps.thePhraseOWordUsage.pickedPhrasesOWords) {
        boldTheSelectedPhraseOWord(thePhraseOWord);
    }
}

function boldTheSelectedPhraseOWord(phraseOWord) {
    let thePhraseOWordIdx = theProps.thePhraseOWordUsage.pickedPhrasesOWords.findIndexByPhraseOWord(phraseOWord);
    boldThePhraseOWord(phraseOWord, thePhraseOWordIdx);
}


function chooseOptionWords(e) {

    // console.log("chooseOptionWords with key",e.key);

    if (!isValidObj(theSentenceDiv.value)) {
        // console.log("chooseOptionWords invoked");
        return;
    }
    let allIndexMarks = theSentenceDiv.value.querySelectorAll("sub[" + HILITER_ATTR + "]");
    // logTheResult("e.key :" + e.key + ", e.code : " + e.code);
    if (parseInt(e.key) <= allIndexMarks.length && e.code.startsWith("Digit")) {
        let theIndexMarkNode = allIndexMarks[parseInt(e.key) - 1];
        let wordIdx = theIndexMarkNode.parentNode.getAttribute(PhraseOWordUsage.WORDIDX_ATTR);
        let theWordSpanNode = nodeWordsMapping.wordSpanNodes[nodeWordsMapping["word" + wordIdx]];
        inputingStore.currTempPhraseOWord.startWordMark.startIdx = theWordSpanNode.idx;
        inputingStore.currTempPhraseOWord.startWordMark.word = theWordSpanNode.word;
        inputingStore.currTempPhraseOWord.endWordMark.startIdx = theWordSpanNode.idx;
        inputingStore.currTempPhraseOWord.endWordMark.word = theWordSpanNode.word;
        inputingStore.currTempPhraseOWord.isValidPhraseOWord = true;
        thePhraseOWordPickInput.value.setCurrentInputingValue(theWordSpanNode.word);
        inputingStore.currFilledMoreThanOne = false;
        thePhraseOWordPickInput.value.enableTheInput();

        removeMarkCurrPickIndex();
        removeCurrPickMark();
        //todo mark
        // this[_currHilightIt].removeAllHilighter()
        // this[_currHilightIt] = null;

        // boldCurrTempPhraseOWord()
        document.removeEventListener("keydown", theChooseOptionWordsFunc);
        boldAllPhrasesOWords();
        e.preventDefault();

        if (isInIOS()) {
            thePhraseOWordPickInput.value.disableTheInput();
        }
        // return;
    } else if (e.code === "Escape") {
        e.preventDefault();
        thePhraseOWordPickInput.value.enableTheInput();

        removeMarkCurrPickIndex();
        removeCurrPickMark();
        //todo mark
        // this[_currHilightIt].removeAllHilighter()
        // this[_currHilightIt] = null;
        document.removeEventListener("keydown", theChooseOptionWordsFunc);
        boldAllPhrasesOWords();
        // return;
    } else if (e.key === " " || e.key === "Space") {
        e.preventDefault();
        // if(isInIOS()){
        //     thePhraseOWordPickInput.value.setCurrentInputingValue(inputingStore.pickInputingValue.trim());
        //     document.removeEventListener("keydown", theChooseOptionWordsFunc);
        // }

        // thePhraseOWordPickInput.value.setCurrentInputingValue(inputingStore.pickInputingValue.trim());
    }
}

// console.log(chooseOptionWords);

/**
 *
 * @param phraseOWord phraseOWord {PhraseOWordUsage.PhraseOWord}
 * @param endWordMarkStartIdx
 * @returns {*[]}
 */
function getAllNodesBetween(phraseOWord, endWordMarkStartIdx = null) {
    let startNode = theSentenceDiv.value.querySelector("["
        + PhraseOWordUsage.LANGSECTION_ATTR + "=\"eng\"] ["
        + PhraseOWordUsage.WORDIDX_ATTR + "=\""
        + phraseOWord.startWordMark.startIdx + "\"]");

    // document.querySelector("[wordIdx=\"" + start + "\"]");
    let nextSiblingNode = startNode;
    let foundEnd = false;
    let allBetweenNodesArr = [];
    allBetweenNodesArr.push(startNode);
    if (!isValidObj(endWordMarkStartIdx)) {
        endWordMarkStartIdx = phraseOWord.endWordMark.startIdx;
    }

    if (phraseOWord.startWordMark.startIdx === parseInt(endWordMarkStartIdx)) {
        return allBetweenNodesArr;
    }

    /* eslint-disable-next-line */
    while (nextSiblingNode = nextSiblingNode.nextSibling) {
        allBetweenNodesArr.push(nextSiblingNode);
        //此处是两个=号，3个则有问题
        if (nextSiblingNode.nodeName !== "#text" && parseInt(nextSiblingNode.getAttribute(PhraseOWordUsage.WORDIDX_ATTR)) === parseInt(endWordMarkStartIdx)) {
            foundEnd = true;
            break;
        }
    }
    return foundEnd ? allBetweenNodesArr : [];
}


const ATTR_SPLITSUB = "splitSub";
const SPLITTER_SIGN = "♠";

function addSplitter(allNodesBetween) {
    let preSibling = allNodesBetween[0].previousSibling;

    let hasTheAddedSplittingSup = (isValidObj(preSibling) && preSibling.nodeName === "SUB" && preSibling.getAttribute(ATTR_SPLITSUB) === "1");
    if (isValidObj(allNodesBetween) && allNodesBetween.length > 0 && !hasTheAddedSplittingSup) {

        let theParent = allNodesBetween[0].parentNode;

        let theSplittingSub = createSplitterNode();
        theParent.insertBefore(theSplittingSub, allNodesBetween[0]);
    }
}

function createSplitterNode() {
    let theSplittingSub = document.createElement("sub");
    // console.log("the previous node: ",allNodesBetween[0].previousNode);
    theSplittingSub.innerHTML = SPLITTER_SIGN;
    theSplittingSub.setAttribute(ATTR_SPLITSUB, "1");
    theSplittingSub.classList = ["splitSub"];
    return theSplittingSub;
}


function clearBoldsOfPhraseOWord(thePhraseOWordIdx, thePhraseOWord) {

    // console.log("clearing the bold of phraseOWord:",JSON.stringify(thePhraseOWord));
    if (thePhraseOWord.isValidPhraseOWord) {
        // console.log("theSentenceDiv:",theSentenceDiv,theSentenceDiv.value);
        // console.log("the selector:","[" + PhraseOWordUsage.WORDIDX_ATTR + "=\"" + thePhraseOWord.phraseOWordStartIndex + "\"]");
        let preSibling = theSentenceDiv.value.querySelector("[" + PhraseOWordUsage.WORDIDX_ATTR + "=\"" + thePhraseOWord.phraseOWordStartIndex + "\"]").previousSibling;
        let hasTheAddedSplittingSup = (isValidObj(preSibling) && preSibling.nodeName === "SUB" && preSibling.getAttribute("splitSub") === "1");
        if (hasTheAddedSplittingSup) {
            preSibling.parentNode.removeChild(preSibling);
        }
    }

    plainThePhraseOWord(thePhraseOWord, thePhraseOWordIdx);

    // let allBolds = theSentenceDiv.value.querySelectorAll("b[" + PhraseOWordUsage.BoldThePhrasesOWords.WORDBOLD_ATTR + "=\"" + thePhraseOWordIdx + "\"]");
    // for (const aBold of allBolds) {
    //     let theParent = aBold.parentNode;
    //     for (const childNode of aBold.childNodes) {
    //         if (childNode.nodeType === 3 || childNode.nodeName === "#text") {
    //             if (childNode.textContent && childNode.textContent.trim() !== "") {
    //                 theParent.replaceChild(childNode.cloneNode(true), aBold)
    //             }
    //         } else {
    //             theParent.appendChild(childNode.cloneNode(true));
    //             theParent.removeChild(aBold);
    //         }
    //     }
    // }
}

function clearAllCurrTempMarkingInfo() {
    removeMarkCurrPickIndex();
    removeCurrPickMark();
    clearBoldsOfCurrTempPhraseOWord();
}

function endPickingTheSentence() {
    // console.log("endPickingTheSentence received, endding....");
    document.removeEventListener("keydown", theChooseOptionWordsFunc);
}


// onBeforeUnmount(()=>{
//     document.removeEventListener("keydown", theChooseOptionWordsFunc);
// })

// function debugIt() {
//     // toWatchObj.value.innerHTML = "sdfsd1";
//     // console.log("theInputingStartWithNodeSpans :", theInputingStartWithNodeSpans.value);
// }

onMounted(() => {
    boldAllPickedPhrasesOWords();
})

</script>

<style scoped>
/*>>>*/
/deep/ .currPicking {
    /*text-decoration: underline 4px double rgba(0, 145, 255, 0.4);*/
    /*text-decoration-skip-ink: none;*/
    background-color: rgba(0, 145, 255, 0.4);
}

/deep/ sub {
    font-size: 8px;
}

/deep/ .splitSub {
    font-size: 8px;
}

</style>